Skip to content

Add the WolfCertTransport to extend the portability on embedded platforms - #15

Merged
Frauschi merged 6 commits into
wolfSSL:mainfrom
yosuke-wolfssl:feat/port
Sep 8, 2026
Merged

Add the WolfCertTransport to extend the portability on embedded platforms#15
Frauschi merged 6 commits into
wolfSSL:mainfrom
yosuke-wolfssl:feat/port

Conversation

@yosuke-wolfssl

@yosuke-wolfssl yosuke-wolfssl commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Problem

wolfCert could not run on a stack without BSD sockets. It had a hook for
opening a connection (connect_cb, shaped as a file descriptor) but kept
ownership of the socket lifecycle: close, fcntl, send and recv sat
inline in src/http.c, and the raw descriptor went into wolfSSL through
wolfSSL_set_fd, which overwrites any custom CBIO context the application had
installed. src/csr.c and src/store.c also required POSIX headers.

Fix (src/http.c)

A WolfCertTransport vtable now owns every byte on the wire, TLS records
included:

typedef struct WolfCertTransport {
    int  (*connect)(void* ctx, const char* host, int port,
                    int timeout_ms, void** conn);
    int  (*read)(void* ctx, void* conn, uint8_t* buf, size_t len,
                 int timeout_ms);
    int  (*write)(void* ctx, void* conn, const uint8_t* buf, size_t len,
                  int timeout_ms);
    int  (*disconnect)(void* ctx, void* conn);
    void* ctx;
} WolfCertTransport;

Callers embed it by value in the three config structs. Leaving it zeroed
selects the built-in POSIX instance; a half-filled one is WOLFCERT_ERR_BAD_ARG.
It is copied when the connection opens, so only ctx must outlive it.

  • src/net_posix.c carries the built-in POSIX instance, making it one
    implementation of the vtable rather than a privileged path. It calls recv
    and send directly and depends on none of wolfSSL's optional
    wolfIO_Send/wolfIO_Recv helpers, which are absent under
    WOLFSSL_USER_IO, MICRIUM, WOLFSSL_CONTIKI and WOLFSSL_NO_SOCK.
  • An internal CBIO bridge routes wolfSSL's record I/O through the same
    read/write pair, and wolfSSL_set_fd is gone from the client. The bridge
    is on every path including the default one, so the existing round-trip suite
    exercises it.
  • src/http.c performs no syscall and includes no POSIX header. Neither do
    src/csr.c, where a local IP-literal parser replaces inet_pton, or
    src/store.c, whose file backend is now compile-gated.

Additions:

Addition Header
WolfCertTransport, plus a transport field on the three config structs wolfcert/types.h, wolfcert/http.h
WOLFCERT_ERR_CONN_CLOSED (-16) wolfcert/errors.h
WOLFCERT_HAVE_BUILTIN_TRANSPORT, WOLFCERT_HAVE_POSIX_STORE generated wolfcert/options.h

Breaking changes — recompile, do not just relink:

Change Migration
WolfCertConnectFn and the connect_cb / connect_ctx fields are gone fill in a WolfCertTransport; wolfcert_posix_connect() stays public so a custom connect can open its TCP leg with it
transport is embedded by value, so the config structs grow .transport = &t becomes .transport = t
wolfSSL HAVE_SNI is now required rebuild wolfSSL with --enable-sni, or define WOLFCERT_NO_SNI when every endpoint serves a single certificate
a user_settings.h build must state each platform gate define WOLFCERT_HAVE_BUILTIN_TRANSPORT / _POSIX_STORE, or the matching WOLFCERT_NO_*
*_session_fd() returns -1 under a caller-supplied transport drive the loop from the transport's own readiness signal
the built-in transport's descriptor is always O_NONBLOCK; a blocking session's used not to be poll it for readiness rather than reading or writing it directly

Tests

tests/unit/test_transport.c drives the whole HTTP path through a scripted
transport with no sockets, threads or TLS, so it runs in every build
configuration: handle 0 is a valid handle, disconnect runs exactly once,
the vtable is copied so the caller's may die with its frame, a half-filled
vtable is rejected before anything is dialled while a zeroed one takes the
built-in transport, the parser survives a byte-at-a-time feed, and a body may
end at CONN_CLOSED. A transport that breaks the contract — returning 0 for
EOF, a positive connect code, or more bytes than were requested — is refused
rather than trusted.

Verification

  • CMake and autoconf both clean under -Werror. 27 of 27 tests pass on the
    default configuration, and 11 of 11 with 3 skipped when the built-in
    transport and POSIX store are compiled out.
  • ASan and UBSan clean over the full suite. Negative controls back the two
    guards that matter: removing the over-count check reproduces a
    stack-buffer-overflow, and borrowing the vtable instead of copying it
    reproduces a stack-use-after-scope.
  • The no-posix-arm gate compiles all 15 portable sources for a Cortex-M4
    against wolfSSL headers only, and a user_settings.h naming neither platform
    gate now fails at check_config.h instead of silently losing networking.
  • All six commits build and pass their own suite, so the branch is bisect safe.

Not in this PR

  • Async transport.connect. It has no would-block vocabulary, so session
    setup blocks even under cfg.nonblocking. Changing it is a vtable contract
    change and is better done deliberately than folded in here.
  • Coverage for the WOLFCERT_NO_POSIX_STORE stub and for wolfcert_strerror's
    new code.
    Both guard code that cannot regress silently — a missing stub is a
    link error the existing gated CI job already catches.
  • Skipping SNI for an IP-literal host. A live interop bug, but pre-existing
    and independent of this refactor; it sits on its own branch.

@yosuke-wolfssl yosuke-wolfssl self-assigned this Aug 14, 2026
Copilot AI lite review requested due to automatic review settings August 14, 2026 08:09

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors wolfCert’s HTTP/TLS I/O so the library no longer assumes BSD sockets: all network traffic (including TLS records) is routed through a new WolfCertTransport vtable, with the POSIX sockets implementation moved into a removable src/net_posix.c. This improves portability for embedded/RTOS targets while keeping the default POSIX path as the built-in transport.

Changes:

  • Introduces WolfCertTransport and threads it through request/session/server configs; deprecates the fd-based connect_cb.
  • Removes POSIX syscalls/headers from core HTTP and CSR paths by adding a CBIO bridge for wolfSSL and a portable IP-literal parser.
  • Adds build/config gating for “platform pieces” (built-in transport and POSIX store), updates tests/CI/docs, and adds WOLFCERT_ERR_CONN_CLOSED.

Reviewed changes

Copilot reviewed 38 out of 38 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
wolfcert/types.h Adds WolfCertTransport and extends config structs with transport.
wolfcert/options.h.in Adds generated feature macros for platform gating.
wolfcert/http.h Exposes transport in public HTTP request/session configs and updates docs/comments.
wolfcert/errors.h Adds WOLFCERT_ERR_CONN_CLOSED.
wolfcert/check_config.h Enforces HAVE_SNI unless WOLFCERT_NO_SNI is defined.
src/http.c Core refactor: transport-owned I/O, wolfSSL CBIO bridge, locale-stable header comparisons, legacy adapter.
src/net_posix.c Implements built-in POSIX WolfCertTransport + legacy connect adapter.
src/internal.h Declares wolfcert_parse_ip and transport helpers/externs.
src/internal.c Implements portable IPv4/IPv6 literal parsing.
src/csr.c Switches SAN iPAddress encoding to wolfcert_parse_ip (removes inet_pton).
src/store.c Compile-gates POSIX store backend and provides stubs when disabled.
src/errors.c Adds strerror text for WOLFCERT_ERR_CONN_CLOSED.
src/est/est_client.c Propagates transport from server cfg into HTTP request/session configs.
src/scep/scep_client.c Propagates transport from server cfg into HTTP request/session configs.
cli/wolfcert_client.c Drops explicit connect_cb use so CLI uses the default built-in transport.
tests/unit/test_transport.c New unit tests covering scripted transport behavior and edge cases.
tests/unit/test_http.c Adds conflict test for connect_cb + transport; marks skip when builtin transport is off.
tests/unit/test_store.c Skips POSIX store tests when POSIX store is compiled out.
tests/unit/test_parse_negative.c Adds negative/positive coverage for new IP literal parser.
tests/unit/test_est.c Marks skip when builtin transport is off.
tests/unit/test_csr.c Adds CSR SAN iPAddress assertions (v4/v6).
tests/integration/test_tls_http.c Marks skip when builtin transport is off.
tests/CMakeLists.txt Adds test_transport, gates socket tests on builtin transport, sets skip return codes.
CMakeLists.txt Adds options for POSIX store / builtin transport and gates sources accordingly.
configure.ac Adds autoconf flags for builtin transport / POSIX store and emits options.h macros.
Makefile.am Gates src/net_posix.c and socket-driven tests on builtin transport.
examples/user_settings.h.example Documents the new platform feature macros for user-settings builds.
scripts/ci/build-wolfssl.sh Enables SNI in the CI wolfSSL build.
scripts/ci/freestanding-user_settings.h Adds a no-sockets/no-files freestanding settings bundle for CI gating.
scripts/ci/compile-freestanding.sh New compile-only “no POSIX headers” gate for portable sources.
.github/workflows/pr.yml Adds CI matrix row for “platform pieces off” and a freestanding ARM compile job.
.github/workflows/nightly.yml Adds nightly run for “platform pieces off” build.
README.md Documents transport vtable portability in feature overview and enables SNI in example configure line.
docs/ARCHITECTURE.md Adds full transport contract/bridge documentation.
docs/EMBEDDED.md Documents targets without sockets/filesystem and new build flags/macros.
docs/MIGRATING-FROM-WOLFSCEP.md Updates migration guidance to use WolfCertTransport instead of connect_cb.
docs/CI.md Documents new CI gates (cmake-no-builtin-transport, no-posix-arm).
CLAUDE.md Updates canonical wolfSSL configure line to include --enable-sni.
Suppressed comments (1)

src/http.c:502

  • wolfcert_cbio_send collapses WOLFCERT_ERR_WANT_READ into WOLFSSL_CBIO_ERR_WANT_WRITE. A transport write() can legitimately return WANT_READ in non-blocking mode; mapping it to WANT_WRITE makes wolfSSL report the wrong condition and breaks event-loop readiness handling.
    switch (r) {
        case WOLFCERT_ERR_WANT_READ:
        case WOLFCERT_ERR_WANT_WRITE:
            return WOLFSSL_CBIO_ERR_WANT_WRITE;
        case WOLFCERT_ERR_CONN_CLOSED:

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/http.c

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fenrir Automated Review — PR #15

Scan targets checked: wolfcert-bugs, wolfcert-src

Findings: 6
6 finding(s) posted as inline comments (see file-level comments below)

This review was generated automatically by Fenrir. Findings are non-blocking.

Comment thread src/http.c Outdated
Comment thread wolfcert/http.h
Comment thread tests/unit/test_transport.c
Comment thread src/net_posix.c Outdated
Comment thread src/http.c
Comment thread tests/unit/test_transport.c
Comment thread src/http.c Outdated
Comment thread wolfcert/http.h
Comment thread tests/unit/test_transport.c
Comment thread src/net_posix.c Outdated
Comment thread src/http.c
Comment thread tests/unit/test_transport.c

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fenrir Automated Review — PR #15

Scan targets checked: none
Failed targets: wolfcert-bugs, wolfcert-src

⚠️ Review incomplete — one or more scan targets failed before findings could be produced. See the Fenrir PR review detail page for logs.

@yosuke-wolfssl
yosuke-wolfssl marked this pull request as draft August 17, 2026 05:54
@yosuke-wolfssl
yosuke-wolfssl marked this pull request as ready for review August 17, 2026 23:25

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fenrir Automated Review — PR #15

Scan targets checked: wolfcert-bugs, wolfcert-src

Findings: 4
4 finding(s) posted as inline comments (see file-level comments below)

This review was generated automatically by Fenrir. Findings are non-blocking.

Comment thread src/http.c
Comment thread tests/unit/test_transport.c
Comment thread src/http.c
Comment thread src/net_posix.c Outdated
Comment thread src/http.c
Comment thread tests/unit/test_transport.c
Comment thread src/http.c
Comment thread src/net_posix.c Outdated

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fenrir Automated Review — PR #15

Scan targets checked: wolfcert-bugs, wolfcert-src

Findings: 4
4 finding(s) posted as inline comments (see file-level comments below)

This review was generated automatically by Fenrir. Findings are non-blocking.

Comment thread src/http.c
Comment thread tests/unit/test_transport.c
Comment thread src/http.c
Comment thread tests/unit/test_transport.c
Comment thread src/http.c
Comment thread tests/unit/test_transport.c
Comment thread src/http.c

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fenrir Automated Review — PR #15

Scan targets checked: wolfcert-bugs, wolfcert-src

Findings: 1
1 finding(s) posted as inline comments (see file-level comments below)

This review was generated automatically by Fenrir. Findings are non-blocking.

Comment thread tests/unit/test_transport.c
Comment thread tests/unit/test_transport.c
@yosuke-wolfssl

Copy link
Copy Markdown
Contributor Author

Hi @Frauschi ,
This is the first PR for core library part.
Please review it once you are back

@yosuke-wolfssl yosuke-wolfssl removed their assignment Sep 3, 2026
Comment thread wolfcert/types.h Outdated
Comment thread wolfcert/types.h Outdated
Comment thread src/internal.h Outdated

@Frauschi Frauschi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Read through the transport series. The shape is right: making the POSIX path one instance of the vtable instead of a privileged path is the correct call, and routing TLS records through the same read/write pair - so the default build exercises the bridge on every test - is the detail that makes it trustworthy rather than just plausible.

One blocker. The two new WOLFCERT_HAVE_* platform gates have no check_config.h guard, so a WOLFCERT_USER_SETTINGS integrator carrying a user_settings.h written before this PR gets a library that compiles and links clean and then fails every request at runtime with no diagnostic. CI can't see it because the header-only job copies the updated example.

The rest is mostly contract gaps in src/net_posix.c. That file is the one every port will copy, so the errno mapping and the timeout_ms > 0 handling are worth getting right there rather than in each integrator's glue. Beyond that: dial() doesn't validate what connect returns, and the session_fd comments in est.h / scep.h still promise a descriptor that a custom transport cannot give.

Nothing here re-opens the SIGPIPE, CBIO-direction or deferred-transport-test threads - those are already answered.

Comment thread wolfcert/check_config.h
Comment thread src/http.c Outdated
Comment thread src/net_posix.c
Comment thread wolfcert/http.h Outdated
Comment thread src/http.c Outdated
Comment thread Makefile.am Outdated
Comment thread src/net_posix.c
Comment thread src/net_posix.c
Comment thread src/http.c Outdated
- WolfCertTransport (connect/read/write/disconnect/ctx) and
  WOLFCERT_ERR_CONN_CLOSED, settable on the three config structs.
- src/net_posix.c carries the built-in POSIX instance.
- http.c moves every byte through the vtable and bridges wolfSSL's CBIO
  onto it, so TLS records and plain HTTP share one path.
- ARCHITECTURE section 4.6 carries the vtable contract, and the
  session_fd contract narrows to the built-in transport.
- scripts/ci/compile-freestanding.sh compiles the portable sources for a
  Cortex-M4 with no POSIX headers; check_config.h requires HAVE_SNI.

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fenrir Automated Review — PR #15

Scan targets checked: wolfcert-bugs, wolfcert-src

Fenrir result: Approved ✅

No new issues found in the changed files.

Advisory only — this automated result does not count as a GitHub approval.

- net_posix.c calls recv and send directly rather than wolfIO_Recv and
  wolfIO_Send, which link only under USE_WOLFSSL_IO.
- WolfCertConnectFn and the connect_cb / connect_ctx fields are gone;
  dial() takes only the transport.
- The three config structs hold a WolfCertTransport by value, copied
  when the connection opens, and wolfcert_transport_fd() replaces
  wolfcert_transport_is_fd_backed().
- read and write take two timeout_ms modes, 0 and negative. ARCHITECTURE
  4.6 also states that honouring len is the transport's responsibility,
  and that wolfcert_http_session_fd() returns an O_NONBLOCK descriptor.
- Makefile.am keeps the conditional test_net entry with check_PROGRAMS.
@yosuke-wolfssl

Copy link
Copy Markdown
Contributor Author

Hi @Frauschi ,
I addressed the issues you mentioned. Please check my inline replies for each detail.
I took documentation option on some of them, but I'm happy to flip it if you have another design.

@Frauschi
Frauschi merged commit ab532eb into wolfSSL:main Sep 8, 2026
23 checks passed
@yosuke-wolfssl
yosuke-wolfssl deleted the feat/port branch September 8, 2026 22:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants